package com.devyk.av.rtmp.library.camera

import android.content.Context
import android.view.Surface
import com.devyk.av.camera_recorder.callback.IGLThreadConfig
import com.devyk.av.camera_recorder.callback.IRenderer
import com.devyk.av.rtmp.library.camera.renderer.DrawToEncodeTextureRenderer
import com.devyk.av.rtmp.library.mediacodec.VideoEncoder
import com.devyk.av.rtmp.library.widget.GLSurfaceView
import java.lang.ref.WeakReference
import javax.microedition.khronos.egl.EGLContext

/**
 * <pre>
 *     author  : devyk on 2020-07-11 15:18
 *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 *     github  : https://github.com/yangkun19921001
 *     mailbox : yang1001yk@gmail.com
 *     desc    : This is CameraRecorder 摄像头预览数据录制器
 * </pre>
 */
class CameraPreviewRecorderAndEncoder(
    context: Context,
    textureId: Int,
    eglContext: EGLContext?
) :
    VideoEncoder(),
    IGLThreadConfig {

    /**
     * 基本原理是使用了 GLSurfaceView 绑定的 GLThread 创建的 GLContext,
     * 这样，就能将相机采集渲染到指定 texture 中的图像数据 作为输入数据，然后在自己的渲染进程中，重新渲染一遍，
     * 因为绑定了Surface(由编码器提供), 所以，重新渲染的结果自然能被编码器获取到，编码器再对结果进行编码。
     * 工作流程就是：
     * 1. 创建FBO、相机预览纹理、绑定FBO的纹理
     * 2. 预览线程将触发将相机采集的数据更新到相机预览纹理上
     * 3. 预览线程将相机采集数据
     */
    private var mDrawToEncoderTexture: DrawToEncodeTextureRenderer =
        DrawToEncodeTextureRenderer(context, textureId)
    private var mEGLContext = eglContext
    private var mRendererMode = GLSurfaceView.RENDERER_MODE_CONTINUOUSLY
    private var mGLThread: EncodeRendererThread? = null
    private var mSurface: Surface? = null


    /**
     * surface 创建的时候开始进行 GL 线程渲染
     */
    override fun onSurfaceCreate(surface: Surface?) {
        super.onSurfaceCreate(surface)
        mSurface = surface
        mGLThread = EncodeRendererThread(WeakReference(this))
        mGLThread?.run {
            setRendererSize(mConfiguration.width, mConfiguration.height)
            isCreate = true
            isChange = true
            // 开始相渲染线程
            start()
        }
    }

    override fun stop() {
        super.stop()
        mGLThread?.onDestroy()
    }


    fun pause() {
        mGLThread?.setPause()
    }

    fun resume() {
        mGLThread?.setResume()
    }

    override fun getSurface(): Surface? {
        // 这里 GLThread 启动后，将会使用该 Surface 来初始化 OpenGL es 环境
        // mSurface 是由 MediaCodec 创建的, 并通过 onSurfaceCreate 来设置
        if (mSurface != null)
            return mSurface
        return super.getSurface()
    }

    override fun getRenderer(): IRenderer = mDrawToEncoderTexture

    // 渲染线程使用的是 AVLiveView(GLSurfaceView) 创建的 EGLContext
    override fun getEGLContext(): EGLContext? = mEGLContext

    override fun getRendererMode(): Int = mRendererMode

    fun setWatermark(watermark: Watermark) {
        mDrawToEncoderTexture.setWatermark(watermark)
    }

    /**
     * 摄像头采集到FBO中的数据编码渲染线程
     */
    class EncodeRendererThread(weakReference: WeakReference<IGLThreadConfig>) :
        GLThread(weakReference) {
        init {
            name = "EncodeRendererThread"
        }
    }

    /**
     * 编码完成的 H264 数据
     *   00 00 00 01 06:  SEI信息
     *   00 00 00 01 67:  0x67&0x1f = 0x07 :SPS
     *   00 00 00 01 68:  0x68&0x1f = 0x08 :PPS
     *   00 00 00 01 65:  0x65&0x1f = 0x05: IDR Slice
     */
//    fun onVideoEncodes(bb: ByteBuffer?, bi: MediaCodec.BufferInfo) {
//        var h264Arrays = ByteArray(bi.size)
//        bb?.position(bi.offset)
//        bb?.limit(bi.offset + bi.size)
//        bb?.get(h264Arrays)
//        val tag = h264Arrays[4].and(0x1f).toInt()
//        if (tag == 0x07) {//sps
//            LogHelper.e(TAG, " SPS " + h264Arrays.size)
//        } else if (tag == 0x08) {//pps
//            LogHelper.e(TAG, " PPS ")
//        } else if (tag == 0x05) {//关键字帧
//            LogHelper.e(TAG, " 关键帧 " + h264Arrays.size)
//        } else {
//            //普通帧
//            LogHelper.e(TAG, " 普通帧 " + h264Arrays.size)
//        }
//    }

}